import { Inject, Injectable, Logger, forwardRef } from '@nestjs/common';
import { ChatRoomEntity } from '@common/database/entity/chat_room.entity';
import { Repository } from 'typeorm';
import { ApiFail } from '@common/utils';
import { UserService } from '@game/user/user.service';
import { RedisService } from '@common/reids/redis.service';
import { defaultConfig } from '@game/config/config';
import { ChatSceneEntity } from '@common/database/entity/chat_scene.entity';
import { ChatRoundEntity } from '@common/database/entity/chat_round.entity';
import { User } from '@common/database/entity/user.entity';
import { ChargeRecord } from '@common/database/entity/charge_record.entity';
import { RoomService } from './room/room.service';
import { RoomDto } from './dto/room.dto';
import { RebotService } from './rebot/rebot.service';

@Injectable()
export class WebSocketService {
  logger: Logger;
  constructor(
    @Inject('CHAT_ROOM_GREPOSITORY')
    public readonly repo: Repository<ChatRoomEntity>,
    @Inject('CHAT_SCENE_GREPOSITORY')
    public readonly repoScene: Repository<ChatSceneEntity>,
    private authServe: UserService,
    public readonly redisService: RedisService,
    @Inject('CHAT_ROUND_GREPOSITORY')
    public readonly repoRound: Repository<ChatRoundEntity>,
    public readonly roomService: RoomService,
    @Inject(forwardRef(() => RebotService))
    public readonly rebotService: RebotService,
    @Inject('CHAT_ROOM_GREPOSITORY')
    public readonly repoRoom: Repository<ChatRoomEntity>,
  ) {
    this.logger = new Logger('WebSocket');
  }

  async isExist(body: RoomDto, req: any) {
    const data = { roomId: null, type: null };
    data.roomId = body['roomId'];
    // 查询是否有这个房间 type: [">", -1]
    const roomobj = await this.repo
      .createQueryBuilder('room')
      .where('room.roomId =:start_at', { start_at: data.roomId })
      .andWhere('room.isAdmin = :start_at2', { start_at2: 1 })
      .andWhere('room.type > :start_at3', { start_at3: -1 })
      .getOne();
    if (!roomobj) {
      data.type = 'error';
      throw new ApiFail(600, '房间不存在');
    }
    // 这里需要做一个用户存在的拦截  不同环境下的缓存  id会乱  导致下面的流程数据查不到
    const userId = req.user.userId;
    console.log(req.user);
    if (!userId) {
      throw new ApiFail(401, '未登录');
    }

    const user: any = await this.authServe.isValidUser({
      id: userId,
    });
    if (!user) {
      throw new ApiFail(401, '不是本系统用户');
    }
    return roomobj;
  }

  name = [
    '逍遥阁',
    '春一万',
    '夏三条',
    '秋八筒',
    '中发白',
    '将门淑女',
    '欢乐时刻',
    '东风阁',
    '西厢苑',
    '南宫楼',
    '北皇厅',
  ];
  async createRoomAction(body: any, req: any) {
    const data = { roomId: null, isAsk: null, userId: null, roomName: null };
    data.roomId = body.roomId || this.randomString(6);
    data.isAsk = body.isAsk;

    const userId = req.user.userId;

    data.userId = userId;

    data.roomName = body.roomName || this.name[Math.round(Math.random() * 10)];
    console.log(data);
    // 创建房间
    if (!data.roomId || !data.roomName) {
      throw new ApiFail(600, '参数错误');
    }
    const game = await this.redisService.del('game' + data.roomId);
    if (game) {
      this.logger.debug(data.roomId + 'room 清空缓存');
    }
    const user: any = await this.authServe.isValidUser({
      id: userId,
    });
    if (!user) {
      throw new ApiFail(401, '不是本系统用户');
    }

    const roomobj2 = await this.repo.findOne({
      where: { roomId: data.roomId, isAdmin: 1 },
    });

    if (roomobj2) {
      throw new ApiFail(600, '房间已存在或已解散');
    }
    let roomobj: any = {};
    const currentTime = new Date().getTime();

    roomobj = {
      userName: data.userId,
      roomId: data.roomId,
      ownerId: data.userId,
      userId: data.userId,
      isAsk: data.isAsk,
      create_time: currentTime,
      roomName: data.roomName,
      role: 'real',
      isAdmin: 1,
    };
    const ChatRoomEntity = await this.repo.save(roomobj);
    const scene = {
      userName: data.userId,
      roomId: data.roomId,
      ownerId: data.userId,
      userId: data.userId,
      status: 3,
      sceneName: data.roomName,
      gameNum: body.gameNum || 4,
      seat: body.seat || 4,
      model: body.model || 1,
      isFangPao: body.isFangPao || 1,
      qiShouHu: JSON.stringify(body.qiShouHu) || '',
      isDaHu: JSON.stringify(body.isDaHu) || '',
      mashu: body.mashu || 2,
      allhz: body.allhz || 0,
      hz2: body.hz2 || 1,
    };
    const sceneEntity = await this.repoScene.save(scene);
    roomobj.id = ChatRoomEntity.id;

    console.log('roomobj', roomobj);
    console.log('sceneEntity', sceneEntity);

    return roomobj;
  }

  async userJoinByExistRoomAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.ownerId = body.ownerId;
    data.isAsk = body.isAsk;

    // 创建房间
    if (!data.roomId) {
      throw new ApiFail(600, '参数错误');
    }
    const roomobj = await this.repo.findOne({
      where: { roomId: data.roomId, isAdmin: 1 },
    });
    // /此人在不在房间记录里
    if (!roomobj) {
      throw new ApiFail(500, '房间不存在');
    }
    const roomobj2 = await this.repo.findOne({
      where: { roomId: data.roomId, userId: data.userId },
    });
    // 如果是被踢的 就不能进了
    if (roomobj2 && roomobj2.type == -2) {
      throw new ApiFail(600, '当前被踢出房间，请联系房主');
    }
    if (!roomobj2) {
      //关联一下user 需要昵称
      // 4个玩家后提示报错
      const num = await this.repo
        .createQueryBuilder('room')
        .where('room.roomId =:start_at', { start_at: data.roomId })
        .andWhere('room.type != :start_at2', { start_at2: -2 })
        .getCount();
      if (num == 4) {
        throw new ApiFail(501, '玩家已满');
      }
      const data2: any = {
        roomId: roomobj.roomId,
        roomName: roomobj.roomName, //想歪路子拿的
        userId: data.userId,
        ownerId: roomobj.ownerId,
        isAsk: roomobj.isAsk,
        type: 1, //  待进群状态
        isAdmin: 0,
      };
      throw new ApiFail(601, null, data2);
    }
    // 重连进入
    throw new ApiFail(602, null, roomobj2);
  }
  async ready(body: any) {
    const roomInfo: any = await this.getRoomInfoAction(body);
    const result = await this.getRoomUsersAction({...body,...roomInfo});
    let game: any = {};
    roomInfo.users = result.onlines;

    game = await this.rebotService.beginBefore({...roomInfo,numOfGames:result.numOfGames});

    const userId = body.userId;
    let data = {};
    for (let index = 0; index < game.gameSeats.length; index++) {
      const user = game.gameSeats[index];
      const onlineUser = result.onlines[index];
      if (user.userId == userId) {
        user.ready = body.isReady?1:0;
        //准备状态存入库
        onlineUser.ready = body.isReady?1:0;
        data = user;
        break;
      }
    }
    this.readyRoomAction(body);
    //更新缓存
    this.roomService.setUsersInRoom(result.onlines, body.roomId);
    return {...body,...data};
  }
  async beginBefore(body: any, req: any) {
    const roomInfo: any = await this.getRoomInfoAction(body);
    const result:any = await this.getRoomUsersAction({...body,...roomInfo});
    let game = null;
    const userId = req.user.userId;
    roomInfo.users = result.onlines;
    game = await this.redisService.hget('game' + body.roomId);
    // Logger.debug(game)
    if(!game){
      game = await this.rebotService.beginBefore({...roomInfo,numOfGames:result.numOfGames});
    }
    //测试开始
  //  game = await this.rebotService.beginBefore(roomInfo);
    
    // delete  roomInfo.users
    return {...game, userId: userId,numOfGames:result.numOfGames };
  }
  async gameOver(body: any){

    const roomInfo: any = await this.getRoomInfoAction(body);

    let game = await this.redisService.hget('game' + body.roomId);
    // Logger.debug(game)
    
    if((roomInfo.numOfGames+1) >= roomInfo.maxGames){

      game = await this.rebotService.gameOver(roomInfo);
      return "ok"
    }else{
      if(roomInfo.numOfGames && roomInfo.numOfGames!=0 && !game){
        throw new ApiFail(500,"对局不存在")
      }
      return "ok"
    }
  }
  async begin(body: any, req: any) {
    const roomInfo: any = await this.getRoomInfoAction(body);
    const result = await this.getRoomUsersAction({...body,...roomInfo});
    const userId = req.user.userId;
    const needNum = roomInfo.members;

    if (roomInfo.isAdmin > 0) {
      roomInfo.users = result.onlines;
      if (result.onlines && needNum - result.onlines.length > 0) {
        const rebotNum = needNum - result.onlines.length;
        await this.rebotService.generateRobot(roomInfo, rebotNum);

        //模拟发送更新
        //  1、加入房间 seats更新
        //  2、更新ready状态
      }

      let game = await this.rebotService.begin({...roomInfo,numOfGames:result.numOfGames});
      body.userId =userId
      this.startGameAction(body);

      await this.redisService.hset({
        key: 'game' + roomInfo.roomId,
        value: { ...game },
        expire: defaultConfig.scoreCacheTime, // 1天  为了就是瞬时刷新过快 导致的mysql问题
      });
      return { ...game, userId: userId };
    } else {
      throw new ApiFail(500, '只能房主开始游戏');
    }
  }

  async joinRoomAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.ownerId = body.ownerId;
    data.isAsk = body.isAsk;
    data.role = body.role;

    // 创建房间
    if (!data.roomId) {
      throw new ApiFail(600, '参数错误');
    }
    const roomobj = await this.repo.findOne({
      where: { roomId: data.roomId, isAdmin: 1 },
    });
    // /此人在不在房间记录里

    const roomobj2 = await this.repo.findOne({
      where: { roomId: data.roomId, userId: data.userId },
    });
    // 如果是被踢的 就不能进了
    if (roomobj2 && roomobj2.type == -2) {
      throw new ApiFail(600, '当前被踢出房间，请联系房主');
    }
    // /此人在不在房间记录里
    if (!roomobj2) {
      const currentTime = new Date().getTime();

      const data2 = {
        userName: data.userId,
        role: data.role,
        roomId: roomobj.roomId,
        userId: data.userId,
        ownerId: roomobj.ownerId,
        isAsk: roomobj.isAsk,
        create_time: currentTime,
        type: 0, //  待进群状态
        isAdmin: 0,
      };
      const res = await this.repo.save(data2);

      const users = await this.repoRoom
        .createQueryBuilder('r')
        .where('r.roomId =:roomId', { roomId: roomobj.roomId })
        .andWhere('r.type =:type', { type: 0 })
        .orderBy('r.sort', 'DESC')
        .addOrderBy('r.createdAt', 'DESC')
        .leftJoinAndSelect(ChargeRecord, 'd', 'r.userId = d.userId')
        .leftJoinAndSelect(User, 'c', 'r.userId = c.id')
        .select([
          'r.*',
          'c.nickName as nickName',
          'c.weixin_openId as weixin_openId',
          'd.startTime as startTime',
          'd.endTime as endTime',
          'd.role as vipRole',
        ])
        .getRawMany();
      await this.redisService.hset({
        key: 'roomUsers' + roomobj.roomId,
        value: users,
        expire: defaultConfig.scoreCacheTime,
      });

      return res;
    }
    const res = await this.repo
      .createQueryBuilder()
      .update(ChatRoomEntity)
      .set({ type: 0 })
      .where('id = :id', { id: roomobj2.id })
      .execute();

    return res;
  }
  async exitRoomAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.type = body.type || -1;

    // 创建房间
    if (!data.roomId) {
      throw new ApiFail(600, '参数错误');
    }

    const roomobj: any = await this.repo
      .createQueryBuilder('room')
      .where('room.roomId =:start_at', { start_at: data.roomId })
      .andWhere('room.userId =:userId', { userId: data.userId })
      .andWhere('room.type != :start_at2', { start_at2: -2 })
      .getOne();
    if (!roomobj) {
      throw new ApiFail(0, '加入不存在');
    }
    data.id = roomobj.id;

    // const res = await this.repo.update({ id: data.id }, data);
    const res = await this.repo
      .createQueryBuilder()
      .update(ChatRoomEntity)
      .set({ type: data.type })
      .where('id = :id', { id: data.id })
      .execute();
    if (res.affected > 0) {
      return '成功';
    } else {
      throw new ApiFail(600, '参数错误');
    }
  }
  async tirenRoomAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.type = body.type || -1;

    // 创建房间
    if (!data.roomId) {
      throw new ApiFail(600, '参数错误');
    }

    const roomobj: any = await this.repo
      .createQueryBuilder('room')
      .where('room.roomId =:start_at', { start_at: data.roomId })
      .andWhere('room.userId =:userId', { userId: data.userId })
      .getMany();
    if (!roomobj) {
      data.type = 'error';
      throw new ApiFail(0, '加入不存在');
    }
    data.id = roomobj.id;
    const res = await this.repo
      .createQueryBuilder()
      .update(ChatRoomEntity)
      .set({ type: data.type })
      .where('id = :id', { id: data.id })
      .execute();

    if (res.affected > 0) {
      return '成功';
    } else {
      throw new ApiFail(600, '参数错误');
    }
  }

  async getRoomInfoAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.type = -1;

    // 创建房间
    if (!data.roomId) {
      throw new ApiFail(600, '参数错误');
    }
    // const dataView = await this.redisService.hget('createroom_' + data.roomId);
    const dataView = null;
    let roomobj: any = {};
    if (!dataView) {
      const queryBuilder = this.repo.createQueryBuilder('room');
      roomobj = await queryBuilder
        .leftJoinAndSelect(ChatSceneEntity, 'c', 'c.roomId = room.roomId')
        .where('room.roomId =:start_at', { start_at: data.roomId })
        .andWhere('room.isAdmin =:start_at2', { start_at2: 1 })
        .select(
          `
          room.*,
          c.userId as ownerId,
          c.seat as members,
          c.qiShouHu,
          c.isDaHu,
          c.isFangPao,
          c.is_ad,c.status,c.id as sceneId,c.sceneName,c.createdAt,c.model,c.gameNum as maxGames
        `,
        )
        .getRawOne();
      Logger.debug(roomobj)
      await this.redisService.hset({
        key: 'createroom_' + data.roomId,
        value: { ...roomobj },
        expire: defaultConfig.scoreCacheTime, // 3秒  为了就是瞬时刷新过快 导致的mysql问题
      });
    } else {
      roomobj = dataView;
    }

    if (!roomobj) {
      throw new ApiFail(600, '房间不存在' + data.roomId);
    }

  
    
    return {
      ...roomobj,
      userId: data.userId,
      // numOfGames: num,
      title: roomobj.sceneName,
      role:
        data.userId == roomobj.ownerId
          ? 1
          : 459896 == data.roomId
          ? 2
          : roomobj.role,
      roomId: data.roomId,
    };
  }

  async getRoomUsersAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.type = -1;
    if (!data.roomId) {
      throw new ApiFail(600, '参数错误');
    }
    //查库缓存redis
    const users = await this.roomService.getUsersInRoom(data);
    console.log(users.map((item) => item.userId));
    // var  memebers = await this.model("room", "", "api").onLineUserByRoom({users})
    const onlines:any = await this.roomService.memebers(users);
  // 回合初始值
  const round:any = await this.repoRound.find({
    where: { sceneId: body.sceneId },
    order: {
      'createdAt': 'DESC',
    },
  });
  let num = round.length;
  console.log('num:', num);
  if(num>0){
    let finalScoresObj = JSON.parse(round[0].scores);
    let rsData =finalScoresObj.results
    
    for (let index = 0; index < onlines.length; index++) {
      const element = onlines[index];
      element.score =(rsData[index].score)
    }
    
  }
    return {onlines,  numOfGames: num};
  }

  async getUserInfoAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.type = -1;
    if (!data.roomId) {
      throw new ApiFail(600, '参数错误');
    }
    let roomobj: any = {};

    const queryBuilder = this.repo.createQueryBuilder('room');

    roomobj = await queryBuilder
      .leftJoinAndSelect(User, 'c', 'c.id = room.userId')
      .leftJoinAndSelect(ChargeRecord, 'd', 'd.userId = room.userId')
      .where('room.roomId =:start_at', { start_at: data.roomId })
      .andWhere('room.userId =:userId', { userId: data.userId })
      .select(
        `
      room.*,
      c.nickName,c.avatar,c.weixin_openId,d.startTime,d.endTime,d.role as vipRole
    `,
      )
      .getRawOne();

    if (!roomobj) {
      throw new ApiFail(600, '用户不存在');
    }
    // return this.json({ errno: 0, data: { ...roomobj, status: 3 } });
    return { ...roomobj, status: 2 };
  }

  // 批量排序
  async sortUserByRoomAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.sortsIds = body.sortsIds;

    if (!data.roomId) {
      throw new ApiFail(600, '参数错误');
    }
    let res = 0;
    for (let index = 0; index < data.sortsIds.length; index++) {
      const item = data.sortsIds[index];

      await this.repo
        .createQueryBuilder()
        .update(ChatRoomEntity)
        .set({ sort: item.sort })
        .where('roomId = :roomId', { roomId: data.roomId })
        .andWhere('userId = :userId', { userId: item.userId })
        .execute();

      res = res + 1;
    }

    console.log(res);
    if (res == data.sortsIds.length) {
      return '成功';
    } else {
      throw new ApiFail(600, '操作失败');
    }
  }

  async roleRoomAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.role = body.role;
    const res = await this.repo
      .createQueryBuilder()
      .update(ChatRoomEntity)
      .set({ role: data.role })
      .where('roomId = :roomId', { roomId: data.roomId })
      .andWhere('userId = :userId', { userId: data.userId })
      .execute();
    console.log(res);
    if (res) {
      return '成功';
    } else {
      throw new ApiFail(600, '操作失败');
    }
  }
  async readyRoomAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;
    data.ready = body.isReady;
    const res = await this.repo
      .createQueryBuilder()
      .update(ChatRoomEntity)
      .set({ ready: data.ready })
      .where('roomId = :roomId', { roomId: data.roomId })
      .andWhere('userId = :userId', { userId: data.userId })
      .execute();
    console.log(res);
    if (res) {
      return '成功';
    } else {
      throw new ApiFail(600, '操作失败');
    }
  }

  async startGameAction(body: any) {
    const data: any = {};
    data.roomId = body.roomId;
    data.userId = body.userId;

    const res = await this.repo
      .createQueryBuilder()
      .update(ChatSceneEntity)
      .set({ status: 2 })
      .where('roomId = :roomId', { roomId: data.roomId })
      .andWhere('userId = :userId', { userId: data.userId })
      .execute();
    console.log(res);
    if (res) {
      return '成功';
    } else {
      throw new ApiFail(600, '操作失败');
    }
  }

  randomString(e) {
    e = e || 10;
    const t = '0123456789';
    const a = t.length;
    let n = '';
    for (let i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a));
    return n;
  }
}
